import os
import re
import time
import datetime
from Common.handle_log import do_log
from Common.handle_path import SCREENSHOT_DIR, SCREENSHOT_QRCODE_DIR
from Common.connect_to_device import *  # 全局驱动 d 重要，勿删！
from Common.handle_yaml import do_yaml
from functools import cache

package_name = do_yaml.read("iqiyi", "package_name")
screen_status = do_yaml.read("iqiyi", "screen_status")

import uiautomator2 as u2
from pytest_monitor_plugin import platform_recorder


class BasePage:

    def __init__(self, device):
        self.d = device

    def get_element(self, loc):
        try:
            loc = self.d + loc
            ele = eval(loc)
        except:
            do_log.exception("{} 元素表达式格式错误无法转换".format(loc))
            raise
        else:
            return ele

    # 等待元素存在
    def wait_ele_exists(self, loc, img_desc, timeout=10):
        start = datetime.datetime.now()  # 用datetime模块获取时间
        try:
            ele = self.get_element(loc)
            if not (ele.exists(timeout=timeout)):
                raise Exception
        except:
            do_log.exception("等待 {} 元素 {} 存在失败！".format(img_desc, loc))
            if '.child(textMatches=".+")' in loc:  # 文本获取失败，不用截图
                pass
            else:
                self.save_img(img_desc)
            raise
        else:
            end = datetime.datetime.now()  # 用datetime模块获取当前时间
            do_log.info("等待 {} 元素 {} 存在成功。耗时：{}".format(img_desc, loc, end - start))

    def wait_ele_gone(self, loc, img_desc, timeout=60):
        start = datetime.datetime.now()  # 用datetime模块获取时间
        try:
            ele = self.get_element(loc)
            if not (ele.wait_gone(timeout=timeout)):
                raise Exception
        except:
            do_log.exception("等待 {} 元素 {} 消失失败！".format(img_desc, loc))
            self.save_img(img_desc)
            raise
        else:
            end = datetime.datetime.now()  # 用datetime模块获取当前时间
            do_log.info("等待 {} 元素 {} 消失成功。耗时：{}".format(img_desc, loc, end - start))

    # 判断当前页面元素是否存在
    def judge_ele_exists(self, loc):
        ele = self.get_element(loc)
        if ele.exists:
            do_log.info("{} 元素在当前界面中存在".format(loc))
            return True
        else:
            do_log.info("{} 元素在当前界面中不存在".format(loc))
            return False

    # 判断当前页面所有的元素是否存在
    def judge_all_ele_exists(self, loc_list):
        for loc in loc_list:
            ele = self.get_element(loc)
            if not ele.exists:
                do_log.info("{} 元素在当前界面中不存在".format(loc))
                return False
            do_log.info("{} 元素在当前界面中存在".format(loc))
        return True

    # 先等待当前页面元素
    def _deal_element(self, loc, img_desc, timeout=10):  # 为了加速测试修改为3秒
        self.wait_ele_exists(loc, img_desc, timeout=timeout)
        return self.get_element(loc)

    # 获取元素数量
    def get_element_count(self, loc, img_desc, timeout=10):
        ele = self._deal_element(loc, img_desc, timeout=timeout)
        try:
            count = ele.count
            do_log.info("获取 {} 元素 {} 数量为 {}!".format(img_desc, loc, count))
            return count
        except:
            do_log.exception("获取 {} 元素 {} 数量失败!".format(img_desc, loc))
            self.save_img(img_desc)
            raise

    # 点击元素
    def click_element(self, loc, img_desc, timeout=10, offset=(0.5, 0.5)):
        ele = self._deal_element(loc, img_desc, timeout=timeout)
        try:
            ele.click(offset=offset)
            do_log.info("点击 {} 元素 {} 成功！".format(img_desc, loc))
        except:
            do_log.exception("点击 {} 元素 {} 失败!".format(img_desc, loc))
            self.save_img(img_desc)
            raise

    # 连续点击元素
    def click_element_times(self, loc, times, img_desc, timeout=10, offset=(0.5, 0.5)):
        ele = self._deal_element(loc, img_desc, timeout=timeout)
        try:
            for i in range(0, times):
                ele.click(offset=offset)
                # time.sleep(0.1)
            do_log.info("点击 {} 元素 {} 成功！".format(img_desc, loc))
        except:
            do_log.exception("点击 {} 元素 {} 失败!".format(img_desc, loc))
            self.save_img(img_desc)
            raise

    # 长按元素
    def long_click_element(self, loc, img_desc, timeout=10, click_time=1):
        ele = self._deal_element(loc, img_desc, timeout=timeout)
        try:
            ele.long_click(click_time)
            do_log.info("点击 {} 元素 {} 成功！".format(img_desc, loc))
        except:
            do_log.exception("点击 {} 元素 {} 失败!".format(img_desc, loc))
            self.save_img(img_desc)
            raise

    def click_element_geted(self, loc, img_desc, timeout=10):
        ele = loc
        try:
            ele.click()
            do_log.info("点击 {} 元素 {} 成功！".format(img_desc, loc))
        except:
            do_log.exception("点击 {} 元素 {} 失败!".format(img_desc, loc))
            self.save_img(img_desc)
            raise

    # 截图
    def save_img(self, img_description):
        """
        :param img_description: 图片的描述 。格式为 页面名称_功能名
        :return:
        """
        now = time.strftime("%Y-%m-%d %H_%M_%S")
        file_path = "{}_{}.jpg".format(now, img_description)
        img_path = os.path.join(SCREENSHOT_DIR, file_path)
        try:
            eval(self.d).screenshot(img_path)
            # === 新增监控插件集成代码 ===
            # 将截图注册到监控平台
            platform_recorder.add_resource(
                resource_type="SCREENSHOT",
                file_path=img_path,  # 截图保存的实际路径
                description=img_description,  # 截图描述
            )
            # === 监控插件集成代码结束 ===

            # 返回截图路径（如果原有逻辑需要）
            return img_path
        except:
            do_log.exception("截图失败！")
        else:
            do_log.info("截图成功，截图存放在：{}".format(img_path))

    def save_img_for_loc(self, loc, img_desc, timeout=10):
        """
        :param timeout:
        :param img_desc:
        :param loc:
        :param img_description: 图片的描述 。格式为 页面名称_功能名
        :return:
        """
        ele = self._deal_element(loc, img_desc, timeout=timeout)
        now = time.strftime("%Y-%m-%d %H_%M_%S")
        file_path = "{}_{}.jpg".format(now, img_desc)
        img_path = os.path.join(SCREENSHOT_DIR, file_path)
        try:
            ele.screenshot().save(img_path)
        except:
            do_log.exception("{} 截图失败！".format(loc))
        else:
            do_log.info("截图成功，截图存放在：{}".format(img_path))

    def BytesIO_img_for_loc(self, loc, img_desc, timeout=10):
        # 截图元素，直接返回字节流
        """
        :param timeout:
        :param img_desc:
        :param loc:
        :return:
        """
        ele = self._deal_element(loc, img_desc, timeout=timeout)
        try:
            res = ele.screenshot()
        except:
            do_log.exception("{} 截图字节流失败！".format(loc))
        else:
            do_log.info("截图字节流成功")
            return res

    def save_img_for_login_qrcode(self):
        """
        :param img_description: 图片的描述 。格式为 页面名称_功能名
        :return:
        """
        # now = time.strftime("%Y-%m-%d %H_%M_%S")
        time.sleep(2)
        file_path = "login.jpg"
        img_path = os.path.join(SCREENSHOT_QRCODE_DIR, file_path)
        try:
            eval(self.d).screenshot(img_path)
        except:
            do_log.exception("登录二维码截图失败！")
        else:
            do_log.info("登录二维码截图成功，截图存放在：{}".format(img_path))

        return img_path

    # 录制视频
    def save_video(self, video_time, video_description):
        now = time.strftime("%Y-%m-%d %H_%M_%S")
        file_path = "{}_{}.mp4".format(video_description, now)
        video_path = os.path.join(SCREENSHOT_DIR, file_path)
        try:
            eval(self.d).screenrecord(video_path)
            time.sleep(video_time)
            eval(self.d).screenrecord.stop()
        except:
            do_log.exception("录制视频失败！")
        else:
            do_log.info("录制视频成功，视频存放在：{}".format(video_path))

    # 获取元素的属性值
    def get_element_attribute(self, loc, attr_name, img_desc, timeout=10):
        ele = self._deal_element(loc, img_desc, timeout=timeout)
        try:
            # info_value = ele.info
            print(ele.info)
            attr_value = ele.info[attr_name]
        except:
            do_log.exception("获取 {} 元素 {} 的属性 {} 失败! ".format(img_desc, loc, attr_name))
            self.save_img(img_desc)
            raise
        else:
            # do_log.info("获取 {} 元素 {} 的属性 {} 值为:{}".format(img_desc, loc, attr_name, info_value))
            do_log.info("获取 {} 元素 {} 的属性 {} 值为:{}".format(img_desc, loc, attr_name, attr_value))
            return attr_value

    # 获取元素的文本值
    def get_text(self, loc, img_desc, timeout=10):
        ele = self._deal_element(loc, img_desc, timeout=timeout)
        try:
            text = ele.get_text()
        except:
            # 日志
            do_log.exception("获取 {} 元素 {} 的文本失败！".format(img_desc, loc))
            # 截图
            # self.save_img(img_desc)
            raise
        else:
            do_log.info("获取 {} 元素 {} 的文本值为:{}".format(img_desc, loc, text))
            return text

    # 输入文本
    def input_text(self, loc, value, img_desc, timeout=10):
        ele = self._deal_element(loc, img_desc, timeout=timeout)
        try:
            ele.set_text(value)
            do_log.info("在 {} 元素 {} 上输入文本值: {} 成功！".format(img_desc, loc, value))
        except:
            do_log.exception("在 {} 元素 {} 上输入文本值: {} 失败！".format(img_desc, loc, value))
            self.save_img(img_desc)
            raise

    # # 判断焦点是否在元素上-通过selected属性
    # def judge_ele_selected(self, loc, img_desc):
    #     if self.judge_ele_exists(loc):
    #         ele = self.get_element(loc)
    #         if ele.info['selected']:
    #             do_log.info("当前焦点在 {} 元素上")
    #         return ele.info['selected']
    #     else:
    #         do_log.exception("{}元素在界面上不存在，无法确定焦点，请检查截图".format(img_desc))
    #         self.save_img(img_desc)
    #         raise

    # 判断焦点是否在元素上-通过selected属性
    def judge_ele_selected(self, loc, img_desc):
        if self.judge_ele_exists(loc):
            # ele = self.get_element(loc)
            if self.get_element_attribute(loc, 'selected', img_desc):
                do_log.info("当前焦点在 {} 元素上".format(loc))
                return True
            else:
                do_log.info("当前焦点不在 {} 元素上".format(loc))
                return False
        else:
            do_log.exception("{} 元素在界面上不存在，无法确定焦点，请检查截图".format(loc))
            self.save_img(img_desc)
            raise

    def start_qrscan_app(self):
        try:
            if self.get_app_current()["package"] != "com.jim.qrcode":
                eval(self.d).app_start("com.jim.qrcode", wait=True)
        except:
            do_log.exception("启动万能扫码失败")
        else:
            do_log.info("启动万能扫码成功")

    def start_ArcLinkSdk_app(self):
        try:
            eval(self.d).app_start("com.arcvideo.ivi.link.tool", wait=True)
            time.sleep(1)
            eval(self.d).app_start("com.arcvideo.ivi.link.tool", wait=True)
        except:
            do_log.exception("启动ArcLinkSdk失败")
        else:
            do_log.info("启动ArcLinkSdk成功")

    def close_ArcLinkSdk_app(self):
        try:
            eval(self.d).app_stop("com.arcvideo.ivi.link.tool")
        except:
            do_log.exception("关闭ArcLinkSdk失败")
        else:
            do_log.info("关闭ArcLinkSdk成功")

    def start_middleware_app(self):
        try:
            if self.get_app_current()["package"] != "com.arcvideo.android.middleware":
                eval(self.d).app_start("com.arcvideo.android.middleware", wait=True)
        except:
            do_log.exception("启动多屏1.0失败")
        else:
            do_log.info("启动多屏1.0成功")

    def get_main_activity(self, package_name):
        try:
            # 执行 dumpsys 获取包的启动 Activity 信息
            result = d_one_device.shell(f"dumpsys package {package_name} | grep -A 1 'MAIN'")

            # 查找包含启动 Activity 的行
            lines = result.splitlines()

            # 如果我们得到了两行输出
            if len(lines) >= 2:
                # 第二行应该包含启动 Activity
                activity_info = lines[1].strip().split()
                if len(activity_info) > 1:
                    return activity_info[1]  # 返回 com.example/.MainActivity 格式的字符串
            return None
        except Exception as e:
            print(f"Error: {e}")
            return None

    def start_IQIYI_app(self):
        try:
            if device_1 in ["4619dd63", "141A36374D523218"]:
                activity_info = self.get_main_activity(package_name)
                d_one_device.shell(f"am start --user 0 --display 0 {activity_info}")
            elif device_1 in ["141A36374D523218"]:
                activity_info = self.get_main_activity(package_name)
                d_one_device.shell(f"am start {activity_info}")

            else:
                eval(self.d).app_start(f"{package_name}")
        except:
            do_log.exception("启动IQYI应用失败")
        else:
            do_log.info("启动IQYI应用成功")

    def close_IQIYI_app(self):
        try:
            eval(self.d).app_stop(f"{package_name}")
        except:
            do_log.exception("关闭IQYI应用失败")
        else:
            do_log.info("关闭IQYI应用成功")

    def close_phone_IQIYI_app(self):
        try:
            eval(self.d).app_stop("com.qiyi.video")
        except:
            do_log.exception("关闭手机IQYI应用失败")
        else:
            do_log.info("关闭手机IQYI应用成功")

    def clear_IQIYI_app(self):
        try:
            eval(self.d).app_clear(f"{package_name}")
        except:
            do_log.exception("恢复IQYI应用状态失败")
        else:
            do_log.info("恢复IQYI应用状态成功")

    def start_geely_settings(self):
        try:
            eval(self.d).app_start("com.geely.pma.settings")
        except:
            do_log.exception("启动极氪车辆设置失败")
        else:
            do_log.info("启动极氪车辆设置成功")

    def start_bilibili(self):
        try:
            eval(self.d).app_start("com.bilibili.bilithings")
        except:
            do_log.exception("启动哔哩哔哩失败")
        else:
            do_log.info("启动哔哩哔哩成功")

    def wait_for_activity(self, activity, img_desc, timeout=10):
        if eval(self.d).wait_activity(activity, timeout=timeout):
            do_log.info("等待 {} activity 页面加载 成功".format(img_desc))
            return True
        else:
            do_log.exception("等待 {} activity页面加载 失败".format(img_desc))
            return False

    def get_app_current(self):
        if device_1 in ["575607c7"]:
            # 执行命令并获取 Display #0 的信息
            window_info = d_one_device.shell(
                "dumpsys window windows | grep -A 10 'Display #0' | grep -E 'mCurrentFocus|Display'")

            # 用于调试：打印获取到的 window 信息
            # print("Window Info:", window_info)

            # 定义正则表达式来匹配包名和活动名，不捕获逗号
            match = re.search(r"displayId=0,.*?(\S+?)/(\S+?)(?=,|\s|$)", window_info)

            # 检查是否找到匹配的包名和活动名
            if match:
                package, activity = match.groups()
                do_log.info("当前前台运行程序为{}".format({'package': package, 'activity': activity}))
                return {'package': package, 'activity': activity}
            else:
                return {}
        else:
            current_app = eval(self.d).app_current()
            do_log.info("当前前台运行程序为{}".format(current_app))
            return current_app

    def get_app_current2(self):
        if device_1 in ["575607c7"]:
            # exclude_packages = ["com.autolink.app.second.hvac","com.autolink.instrument"]
            exclude_packages = ["com.autolink.app.second.hvac"]
            result = d_one_device.shell("dumpsys window | grep mCurrentFocus")
            # 正则表达式匹配包名和活动名称
            matches = re.findall(r'mCurrentFocus=Window\{.* u0 ([a-zA-Z0-9._]+)/([a-zA-Z0-9._]+)', result)

            # 过滤掉系统应用包名并返回第一个非系统应用
            for package, activity in matches:
                if package not in exclude_packages:
                    do_log.info("当前前台运行程序为{}".format({'package': package, 'activity': activity}))
                    return {'package': package, 'activity': activity}

            # 如果没有匹配项返回 None
            return None
        else:
            current_app = eval(self.d).app_current()
            do_log.info("当前前台运行程序为{}".format(current_app))
            return current_app

    def get_ele_center(self, loc, img_desc, timeout=10):
        ele = self._deal_element(loc, img_desc, timeout=timeout)
        try:
            x, y = ele.center()
        except:
            # 日志
            do_log.exception("获取 {} 元素 {} 的中心位置坐标失败！".format(img_desc, loc))
            # 截图
            self.save_img(img_desc)
            raise
        else:
            do_log.info("获取 {} 元素 {} 中心位置坐标为:{},{}".format(img_desc, loc, x, y))
            return x, y

    def install_app(self, path):
        try:
            eval(self.d).app_install(data=path)
        except:
            do_log.exception("推送 {} app 安装失败!".format(path))
            raise
        else:
            do_log.info("推送 {} app 安装成功!".format(path))

    def click_point(self, x, y, img_desc):
        try:
            eval(self.d).click(x, y)
            do_log.info("点击 {} 坐标点{},{}成功！".format(img_desc, x, y))
        except:
            do_log.exception("点击 {} 坐标点{},{}失败！".format(img_desc, x, y))
            self.save_img(img_desc)
            raise

    def swipe(self, Direction, img_desc):
        try:
            eval(self.d).swipe_ext(Direction)
            do_log.info("向{}方向滑动屏幕成功".format(Direction))
        except:
            do_log.exception("向{}方向滑动屏幕失败".format(Direction))
            self.save_img(img_desc)
            raise

    def press_key(self, key):
        keys = {
            "left": "←",
            "right": "→",
            "up": "↑",
            "down": "↓",
            "home": "home",
            "back": "back",
            "enter": "enter",
            "menu": "menu"
        }

        if key in keys:
            try:
                eval(self.d).press(key)
            except Exception as e:
                do_log.exception(f"遥控器按 {keys[key]} 键失败: {str(e)}")
                raise
            else:
                do_log.info(f"遥控器按 {keys[key]} 键成功")
        else:
            do_log.warning(f"未知按键: {key}")

    def open_SCHEME_url(self, url):
        try:
            eval(self.d).open_url(url)
            do_log.info(f"执行SCHEME命令:{url} 成功")
        except:
            do_log.exception(f"执行SCHEME命令:{url} 失败")
            raise

    def push_qrcode_to_mobile(self, device, local_path):
        # device.sync.push(local_path, "/sdcard/DCIM/Camera/888.jpg")
        device.sync.push(local_path, "/sdcard/AAA/999.jpg")
        do_log.info("将截图的的二维码发送至手机")
        device.shell("am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d file:///sdcard/AAA/login.jpg")
        do_log.info("刷新手机相册")

    def timestampTOsecs(self, timestamp):
        # 时间戳转化为秒：{（01:01 =》 61）或(01:01:01 => 3661)}
        strr = timestamp.split(":")
        secs = -1
        if len(strr) == 2:
            secs = int(strr[0]) * 60 + int(strr[1])
        if len(strr) == 3:
            secs = int(strr[0]) * 3600 + int(strr[1]) * 60 + int(strr[2])
        return secs

    @cache
    def get_screen_size(self):
        screen_size = eval(self.d).window_size()
        if screen_status == "wide":
            screen_size_w = max(screen_size)
            screen_size_h = min(screen_size)
            return [screen_size_w, screen_size_h]
        if screen_status == "high":
            screen_size_w = min(screen_size)
            screen_size_h = max(screen_size)
            return [screen_size_w, screen_size_h]

    @cache
    def get_screen_size_pad(self):
        screen_size = eval(self.d).window_size()
        screen_size_w = max(screen_size)
        screen_size_h = min(screen_size)
        return [screen_size_w, screen_size_h]

    def swip_by_score(self, x1_score, y1_score, x2_score, y2_score, duration, img_desc):
        screen_size = self.get_screen_size()
        screen_size_w = screen_size[0]
        screen_size_h = screen_size[1]
        print(screen_size_w, screen_size_h)
        x1 = screen_size_w * x1_score
        x2 = screen_size_w * x2_score
        y1 = screen_size_h * y1_score
        y2 = screen_size_h * y2_score
        print(f"input swipe {x1} {y1} {x2} {y2} {duration}")
        try:
            d_one_device.shell(f"input swipe {x1} {y1} {x2} {y2} {duration}")
            do_log.info("从（{},{})向（{},{})滑动成功".format(x1, y1, x2, y2))
        except:
            do_log.exception("从（{},{})向（{},{})滑动失败".format(x1, y1, x2, y2))
            self.save_img(img_desc)
            raise

    def swip_by_position(self, x1, y1, x2, y2, duration, img_desc):
        try:
            d_one_device.shell(f"input swipe {x1} {y1} {x2} {y2} {duration}")
            do_log.info("从（{},{})向（{},{})滑动成功".format(x1, y1, x2, y2))
        except:
            do_log.exception("从（{},{})向（{},{})滑动失败".format(x1, y1, x2, y2))
            self.save_img(img_desc)
            raise

    def swip_right(self, img_desc):
        try:
            self.swip_by_score(0.2, 0.5, 0.8, 0.5, 200, img_desc)
            do_log.info("向右滑动成功")
        except:
            do_log.exception("向右滑动失败")

    def swipe_by_coordinates(self, x1, y1, x2, y2, duration, img_desc):
        try:
            d_one.swipe(x1, y1, x2, y2, duration)
            do_log.info("从（{},{})向（{},{})滑动成功".format(x1, y1, x2, y2))
        except:
            do_log.exception("从（{},{})向（{},{})滑动失败".format(x1, y1, x2, y2))
            self.save_img(img_desc)
            raise

    def swip_left(self, img_desc):
        try:
            self.swip_by_score(0.8, 0.5, 0.2, 0.5, 200, img_desc)
            do_log.info("向左滑动成功")
        except:
            do_log.exception("向左滑动失败")

    def swip_up(self, img_desc):
        try:
            self.swip_by_score(0.5, 0.7, 0.5, 0.2, 200, img_desc)
            do_log.info("向上滑动成功")
        except:
            do_log.exception("向上滑动失败")

    def swip_down(self, img_desc):
        try:
            self.swip_by_score(0.5, 0.2, 0.5, 0.8, 200, img_desc)
            do_log.info("向下滑动成功")
        except:
            do_log.exception("向下滑动失败")

    def click_point_by_score(self, x, y, img_desc):
        screen_size = self.get_screen_size()
        screen_size_w = screen_size[0]
        screen_size_h = screen_size[1]
        print(screen_size_w, screen_size_h)
        x1 = screen_size_w * x
        y1 = screen_size_h * y
        try:
            eval(self.d).click(x1, y1)
            do_log.info("点击 {} 坐标点{},{}成功！".format(img_desc, x, y))
        except:
            do_log.exception("点击 {} 坐标点{},{}失败！".format(img_desc, x, y))
            self.save_img(img_desc)
            raise

    def longclick_point_by_score(self, x, y, img_desc):
        screen_size = self.get_screen_size()
        screen_size_w = screen_size[0]
        screen_size_h = screen_size[1]
        print(screen_size_w, screen_size_h)
        x1 = screen_size_w * x
        y1 = screen_size_h * y
        try:
            eval(self.d).long_click(x1, y1)
            do_log.info("点击 {} 坐标点{},{}成功！".format(img_desc, x, y))
        except:
            do_log.exception("点击 {} 坐标点{},{}失败！".format(img_desc, x, y))
            self.save_img(img_desc)
            raise

    def doubleClick_point_by_score(self, x, y, img_desc):
        screen_size = self.get_screen_size()
        screen_size_w = screen_size[0]
        screen_size_h = screen_size[1]
        print(screen_size_w, screen_size_h)
        x1 = screen_size_w * x
        y1 = screen_size_h * y
        try:
            eval(self.d).double_click(x1, y1)
            do_log.info("双击 {} 坐标点{},{}成功！".format(img_desc, x, y))
        except:
            do_log.exception("双击 {} 坐标点{},{}失败！".format(img_desc, x, y))
            self.save_img(img_desc)
            raise

    def get_text_loc(self, text):
        text_loc = '(text="#text#")'.replace("#text#", text)
        return text_loc

    def get_textContains_loc(self, text):
        text_loc = '(textContains="#text#")'.replace("#text#", text)
        return text_loc

    def click_text_loc(self, text):
        text_loc = self.get_text_loc(text)
        self.click_element(text_loc, "点击页面上的文字： {}".format(text))

    def judge_textLoc_exists(self, text):
        textLoc = self.get_text_loc(text)
        return self.judge_ele_exists(textLoc)

    def get_xpath_by_id(self, loc):
        id = loc.split('"')[1]
        xpath = "//*[@resource-id='" + id + "']"
        return xpath

    def get_xpath_list_by_id(self, loc):
        id = loc.split('"')[1]
        xpath_list = "//*[@resource-id='" + id + "']/*"
        return xpath_list

    def get_element_BYxpath(self, loc_xpath):
        try:
            d1 = eval(self.d)
            ele = d1.xpath(loc_xpath)
        except:
            do_log.exception("{} 元素表达式格式错误无法转换".format(loc_xpath))
            raise
        else:
            return ele

    def judge_child_IN_parent(self, child_loc, parent_loc):
        parent_xpath_list = self.get_xpath_list_by_id(parent_loc)
        child_id = child_loc.split('"')[1]
        children = self.get_element_BYxpath(parent_xpath_list).all()
        for i, child in enumerate(children):
            if child.info['resourceName'] == child_id:
                return True
        return False

    def get_element_index(self, loc, img_desc, timeout=10):
        ele = self._deal_element(loc, img_desc, timeout=timeout)
        resourceName = self.get_element_attribute(loc, "resourceName", "获取当前落焦的元素resourceID",
                                                  timeout=timeout)
        all_similar_ele_list = self._deal_element(f'(resourceId="{resourceName}")', img_desc, timeout=timeout)
        ele_index = None
        try:
            for index, value in enumerate(all_similar_ele_list):
                if value.info == ele.info:
                    ele_index = index
                    break
        except:
            do_log.exception("获取 {} 元素 {} 的index值失败! ".format(img_desc, loc))
            self.save_img(img_desc)
            raise
        else:
            do_log.info("获取 {} 元素 {} 的属性 index值为:{}".format(img_desc, loc, ele_index))
            return ele_index

    # 判断A在B的direction方向;   direction: "left","right","up","down","child","sibling"
    def judge_locA_locB_direction(self, locA, locB, direction):
        if self.judge_all_ele_exists([locA, locB]) == False:
            return False
        loc = self.d + locB + "." + direction + locA
        if eval(loc) == None:
            do_log.info("元素{}_不在_元素{}的{}侧".format(locA, locB, direction))
            return False
        else:
            if eval(loc).exists:
                do_log.info("元素{}_在_元素{}的{}侧".format(locA, locB, direction))
                return True
            else:
                do_log.info("元素{}_不在_元素{}的{}侧".format(locA, locB, direction))
                return False

    def get_TextLocIndex_in_SameIdLocList(self, id_loc, text):
        ele_list = self.get_element(id_loc)
        for i, ele in enumerate(ele_list):
            # print(f"Index {i}: {ele.info}")
            if ele.info["text"] == text:
                do_log.info("文字元素{}在_id为{}的元素列表中的index为_{}".format(text, id_loc, i))
                return i
        return None

    def get_coordinate_ByLoc(self, loc, img_desc, timeout=10, offset=(0.5, 0.5)):
        ele = self._deal_element(loc, img_desc, timeout=timeout)
        try:
            # ele.click(offset=offset)
            # print(ele.info)
            left = ele.info['bounds']['left']
            top = ele.info['bounds']['top']
            right = ele.info['bounds']['right']
            bottom = ele.info['bounds']['bottom']
            x = left + abs(left - right) * offset[0]
            y = top + abs(top - bottom) * offset[1]
            do_log.info("获取 {} 元素 {} 坐标成功！".format(img_desc, loc))
            return [x, y]
        except:
            do_log.exception("获取 {} 元素 {} 坐标失败!".format(img_desc, loc))
            self.save_img(img_desc)
            raise

    def drag_locA_to_locB(self, locA, offsetA, locB, offsetB):
        coordinate_a = self.get_coordinate_ByLoc(locA, locA, offset=offsetA)
        coordinate_b = self.get_coordinate_ByLoc(locB, locB, offset=offsetB)
        eval(self.d).drag(coordinate_a[0], coordinate_a[1], coordinate_b[0], coordinate_b[1], 0.5)

    @cache
    def judge_mock_env(self):
        # {"code": 21834000, "message": "not found", "success": false}
        # mock
        res = d_one_device.shell("curl https://openapi.danghongyun.com/where")
        if res == "mock":
            return True
        else:
            return False

    def drag_loc_to_position(self, loc, x, y, duration, img_desc, timeout=10):
        ele = self._deal_element(loc, img_desc, timeout=timeout)
        try:
            ele.drag_to(x, y, duration=duration)
            do_log.info("将 元素 拖动到 坐标{} {} 成功！".format(loc, x, y))
        except:
            do_log.exception("将 元素 拖动到 坐标{} {} 失败！".format(loc, x, y))
            self.save_img(img_desc)
            raise

    def swip_left_BYloc(self, loc):
        a = self.get_coordinate_ByLoc(loc, "首页频道栏", offset=(0.8, 0.5))
        b = self.get_coordinate_ByLoc(loc, "首页频道栏", offset=(0.2, 0.5))
        self.swipe_by_coordinates(a[0], a[1], b[0], b[1], 0.03, "依据坐标向左滑动频道栏")

    def swip_right_BYloc(self, loc):
        a = self.get_coordinate_ByLoc(loc, "首页频道栏", offset=(0.2, 0.5))
        b = self.get_coordinate_ByLoc(loc, "首页频道栏", offset=(0.8, 0.5))
        self.swipe_by_coordinates(a[0], a[1], b[0], b[1], 0.03, "依据坐标向右滑动频道栏")

    def get_toast_msg(self, timeout=5):
        try:
            msg = eval(self.d).toast.get_message(wait_timeout=timeout)
        except Exception as e:
            do_log.exception(f"获取Toast消息失败: {str(e)}")
            return None
        else:
            do_log.info(f"获取到的Toast消息为: {msg}")
            return msg




if __name__ == '__main__':
    # d1 = BasePage(device="mobile_vip")
    d1 = BasePage(device="d_one")
    d1.click_element(loc='(text="设置")', img_desc="测试")
    # print(d1.get_app_current())
    # d1.close_IQIYI_app()
    # res=d1.get_element_attribute(loc=f'(resourceId="{package_name}:id/recycler_view",instance="1")',img_desc="测试",attr_name="className")
    # d1.swip_right_BYloc(loc=f'(resourceId="{package_name}:id/recycler_view",instance="1")')
    # d1.get_element_count(loc='(packageName="com.arcvideo.ivi.link.tool",resourceId="android:id/text1")',
    #                      img_desc="测试")
    # d1.close_IQIYI_app()
    # d1.swip_by_score(0.8, 0.7, 0.8, 0.5, duration=200, img_desc="测试")
    # d1.drag_loc_to_position(loc='(resourceId="android:id/move_region")', x=2800, y=100, duration=0.1, img_desc="测试")
    # d1.swip_by_score(0.5, 0.99, 0.5, 0.5, duration=900, img_desc="测试")
    # d1 = BasePage(device="mobile_vip")
    # d1.get_xpath_by_id('(resourceId="com.arcvideo.car.iqy.video:id/ll_search_bar")')
    # d1.judge_child_element_IN_parent_element()
    # print(d1.press_key("back"))
    # d1.click_text_loc("最新 · 自制")
    # res=d1.get_element_attribute(loc='(textContains="为了您的驾驶安全")',img_desc="测试",attr_name="text")
    # res = d1.get_element_attribute(d1.get_text_loc("电视剧"),img_desc="测试",attr_name="text")
    # print(res)
    # d1.save_img("测试截图")
    # d1.swip_up("123")
    # d1.save_img_for_login_qrcode()
    # d1.save_img_for_login_qrcode()
    # d1.click_text_loc("2")
    # d1.save_img_for_loc(loc=f'(resourceId="com.arcvideo.car.iqy.video:id/rv_channel")', img_desc="测试元素截图")
    # d1.save_img_for_login_qrcode()
    # d1.save_img_for_login_qrcode()
    # res = d_one.app_current()
    # print(res)
    # d1.close_IQIYI_app()
    # d1.swip_up("上滑")
    # d1.save_img("123")
    # d1.close_IQIYI_app()
    # d1.swip_up("上滑")
    # d1.click_point(0.08, 0.509, "点击空白处返回")
    # d1.push_qrcode_to_mobile(d_two_device,
    #                          r"/Users/only/Desktop/工作文档/DH/pa           th_code/gitee_code/DH_UIAuto_Base/Outputs/QRScreenshots/login.jpg")
    # d2 = BasePage(device="mobile_vip").open_SCHEME_url('iqiyi://mobile/register_business/qyclient?pluginParams={"biz_id":"103","biz_plugin":"com.qiyi.iphone","biz_params":{"biz_sub_id":69,"kAuthorizeType":1,"biz_params":"Code_type=0&agenttype=23&token=7a068e2240a0cc5773bcf76206689b1ba"}}')
    # d2 = BasePage(device="mobile_vip").open_SCHEME_url(
    #     'iqiyi://mobile/register_business/qyclient?pluginParams={"biz_id":"103","biz_plugin":"com.qiyi.iphone","biz_params":{"biz_sub_id":69,"kAuthorizeType":1,"biz_params":"Code_type=0&agenttype=23&token=7a068e2240a0cc5773bcf76206689b1ba"}}')
    # d2 = BasePage(device="mobile_vip").open_SCHEME_url('iqiyi://mobile/register_business/qyclient?pluginParams=%257B%2522biz_id%2522%253A%2522103%2522%252C%2522biz_plugin%2522%253A%2522com.qiyi.iphone%2522%252C%2522biz_params%2522%253A%257B%2522biz_sub_id%2522%253A69%252C%2522kAuthorizeType%2522%253A1%252C%2522biz_params%2522%253A%2522Code_type%253D0%2526agenttype%253D23%2526token%253D7a068e2240a0cc5773bcf76206689b1ba%2522%257D%257D')
    # d2 = BasePage(device="mobile_vip").open_SCHEME_url('iqiyi://mobile/register_business/qyclient?pluginParams=%7B%22biz_id%22%3A%20%22103%22%2C%20%22biz_plugin%22%3A%20%22com.qiyi.iphone%22%2C%20%22biz_params%22%3A%20%7B%22biz_sub_id%22%3A%2069%2C%20%22kAuthorizeType%22%3A%201%2C%20%22biz_params%22%3A%20%22Code_type%3D0%26agenttype%3D655%26token%3D7a068e22401d22f773bcf7621328abe3a%22%7D%7D')
